package com.dib.neo.bkfs.fs;


import java.io.IOException;
import java.nio.file.AccessDeniedException;
import java.nio.file.FileAlreadyExistsException;
import java.nio.file.FileSystemException;
import java.nio.file.NoSuchFileException;

class BKException extends IOException {

  static final long serialVersionUID = 1L;

  private int errno;
  private String msg;

  BKException(int errno) {
    this.errno = errno;
    this.msg = null;
  }

  BKException(String msg) {
    this.errno = 0;
    this.msg = msg;
  }

  int errno() {
    return errno;
  }

  void setError(int errno) {
    this.errno = errno;
    this.msg = null;
  }

  String errorString() {
    if (msg != null) {
      return msg;
    } else {
      return "errno=" + errno();
    }
  }

  @Override
  public String getMessage() {
    return errorString();
  }

  /**
   * Map well known errors to specific exceptions where possible; otherwise return more general
   * FileSystemException.
   */
  private IOException translateToIOException(String file, String other) {
    // created with message rather than errno
      if (msg != null) {
          return new IOException(msg);
      }

    // handle specific cases
      if (errno() == BKConstants.EACCES) {
          return new AccessDeniedException(file, other, null);
      }
      if (errno() == BKConstants.ENOENT) {
          return new NoSuchFileException(file, other, null);
      }
      if (errno() == BKConstants.EEXIST) {
          return new FileAlreadyExistsException(file, other, null);
      }

    // fallback to the more general exception
    return new FileSystemException(file, other, errorString());
  }

  void rethrowAsIOException(String file) throws IOException {
    IOException x = translateToIOException(file, null);
    throw x;
  }

  void rethrowAsIOException(BKPath file, BKPath other) throws IOException {
    String a = (file == null) ? null : file.getPathForExceptionMessage();
    String b = (other == null) ? null : other.getPathForExceptionMessage();
    IOException x = translateToIOException(a, b);
    throw x;
  }

  void rethrowAsIOException(BKPath file) throws IOException {
    rethrowAsIOException(file, null);
  }

  IOException asIOException(BKPath file) {
    return translateToIOException(file.getPathForExceptionMessage(), null);
  }
}
